package com.rn.simple.docker;

import com.github.dockerjava.api.DockerClient;
import com.github.dockerjava.api.async.ResultCallback;
import com.github.dockerjava.api.command.DockerCmdExecFactory;
import com.github.dockerjava.api.model.*;
import com.github.dockerjava.core.DefaultDockerClientConfig;
import com.github.dockerjava.core.DockerClientBuilder;
import com.github.dockerjava.core.DockerClientConfig;
import com.github.dockerjava.core.command.EventsResultCallback;
import com.github.dockerjava.jaxrs.JerseyDockerCmdExecFactory;
import org.springframework.util.CollectionUtils;

import java.io.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;


/**
 * Description：Docker API工具类
 *
 * @author rannuo
 * @date 2020/2/17
 */
public class DockerUtils {


    private static DockerClient dockerClient;

    /**
     * 获取DOCKER客户端
     *
     * @param dockerClientDTO docker客户端连接信息
     * @return DockerClient
     */
    public static DockerClient getDockerClient(DockerClientDTO dockerClientDTO) {
        // 进行安全认证
        DockerClientConfig config = DefaultDockerClientConfig.createDefaultConfigBuilder()
                // 服务器ip
                .withDockerHost("tcp://" + dockerClientDTO.getHost() + ":" + dockerClientDTO.getPort())
                .withDockerTlsVerify(true)
                // 证书的本地位置
                .withDockerCertPath(dockerClientDTO.getCertAndKeyFilePath())
                // 私钥的本地位置
                //.withDockerConfig(dockerClientDTO.getCertAndKeyFilePath())
                // API版本 可通过在服务器 docker version 命令查看
                .withApiVersion("1.40")
                // 默认
                .withRegistryUrl("https://index.docker.io/v1/")
                // 默认
                .withRegistryUsername(dockerClientDTO.getRegistryUsername())
                // 默认
                .withRegistryPassword(dockerClientDTO.getRegistryPassword())
                // 默认
                .withRegistryEmail(dockerClientDTO.getRegistryEmail())
                .build();

        // docker命令执行工厂
        DockerCmdExecFactory dockerCmdExecFactory = new JerseyDockerCmdExecFactory()
                .withReadTimeout(60000)
                .withConnectTimeout(60000)
                .withMaxTotalConnections(100)
                .withMaxPerRouteConnections(10);

        dockerClient = DockerClientBuilder.getInstance(config).withDockerCmdExecFactory(dockerCmdExecFactory).build();
        return dockerClient;
    }

    public static void main(String[] args) throws InterruptedException, IOException {
        dockerClient = DockerUtils.getDockerClient(new DockerClientDTO("192.168.22.128", "2375", "D:\\JavaDev\\IDEA_J\\simple\\data\\certs"));
//        Info info = queryClientInfo(dockerClient);
//        System.out.println(info);

        String repository = "192.168.22.128:5000/tt-nginx";
        ResultCallback resultCallback = pullImage(dockerClient, repository);
        Info info = queryClientInfo(dockerClient);
        System.out.println(info);
        System.out.println("===================================================finish!!!");
    }

    /**
     * 连接信息
     *
     * @param dockerClient DOCKER客户端
     * @return Object
     */
    public static Info queryClientInfo(DockerClient dockerClient) {
        return dockerClient.infoCmd().exec();
    }

    /**
     * 查看镜像
     *
     * @param dockerClient DOCKER客户端
     * @return Object
     */
    public static List<Image> queryImagesList(DockerClient dockerClient) {
        return dockerClient.listImagesCmd().exec();
    }

    /**
     * 停止容器
     *
     * @param dockerClient DOCKER客户端
     * @param container    容器ID
     * @return Object
     */
    public static Object stopContainer(DockerClient dockerClient, String container) {
        return dockerClient.stopContainerCmd(container).exec();
    }

    /**
     * 删除镜像
     *
     * @param dockerClient DOCKER客户端
     * @param imagesId     镜像ID
     * @return Object
     */
    public static Object removeImages(DockerClient dockerClient, String imagesId) {
        return dockerClient.removeImageCmd(imagesId).exec();
    }

    /**
     * 删除容器
     *
     * @param dockerClient DOCKER客户端
     * @param container    容器ID
     * @return Object
     */
    public static Object removeContainer(DockerClient dockerClient, String container) {
        return dockerClient.removeContainerCmd(container).exec();
    }

    /**
     * 创建容器
     *
     * @param dockerClient DOCKER客户端
     * @param imagesId     镜像ID
     * @return Object
     */
    public static Object createContainer(DockerClient dockerClient, String imagesId) {
        return dockerClient.createContainerCmd(imagesId).exec();
    }

    /**
     * 创建一个镜像
     *
     * @param dockerClient DOCKER客户端
     * @return Object
     * @throws FileNotFoundException 找不到文件
     */
    public static Object createImages(DockerClient dockerClient) throws FileNotFoundException {
        //仓库地址
        String repository = "";
        //镜像文件流
        InputStream imageStream = new FileInputStream("");
        return dockerClient.createImageCmd(repository, imageStream).exec();
    }


    /**
     * 拉取镜像
     *
     * @param dockerClient
     * @param repository
     * @return
     */
    public static ResultCallback pullImage(DockerClient dockerClient, String repository) {
        return dockerClient.pullImageCmd(repository).exec(new ResultCallback<PullResponseItem>() {
            @Override
            public void onStart(Closeable closeable) {

            }

            @Override
            public void onNext(PullResponseItem object) {
                System.out.println(object.getStatus());
            }

            @Override
            public void onError(Throwable throwable) {
                throwable.printStackTrace();
            }

            @Override
            public void onComplete() {
                System.out.println("pull finished");
            }

            @Override
            public void close() throws IOException {

            }
        });
    }

    /**
     * 容器列表(运行中的)
     *
     * @param dockerClient DOCKER客户端
     * @return Object
     */
    public static List<Container> listContainersCmd(DockerClient dockerClient) {
        return dockerClient.listContainersCmd().exec();
    }


    public static List<String> getContainerNameList(List<Container> containerList) {
        List<String> containerNameList = new ArrayList<>();
        for (Container container : containerList) {
            String containerName = container.getNames()[0].replace("/", "");
            containerNameList.add(containerName);
        }
        return containerNameList;
    }

    /**
     * 启动容器
     *
     * @param dockerClient DOCKER客户端
     * @param containerId  容器ID
     */
    public static Object startContainer(DockerClient dockerClient, String containerId) {
        return dockerClient.startContainerCmd(containerId).exec();
    }

    /**
     * 重启容器
     *
     * @param dockerClient 客户端
     * @param containerId  容器id
     * @return java.lang.Object
     * @author wzm
     * @date 2019/9/28 15:30
     */
    public static Object restartContainerCmd(DockerClient dockerClient, String containerId) {
        return dockerClient.restartContainerCmd(containerId).exec();
    }

    /**
     * 从本地上传资源到容器
     *
     * @param dockerClient 客户端
     * @param containerId  容器id
     * @param resource     本地资源路径
     * @param remote       服务器资源路径
     * @return Object
     */
    public static Object copyArchiveToContainerCmd(DockerClient dockerClient, String containerId, String resource, String remote) {
        return dockerClient.copyArchiveToContainerCmd(containerId).withHostResource(resource).withRemotePath(remote).exec();
    }

    /**
     * 从容器下载资源到本地
     *
     * @param dockerClient 客户端
     * @param containerId  容器id
     * @param local        本地路径
     * @param remote       远程容器路径
     * @return Object
     */
    public static Object copyArchiveFromContainerCmd(DockerClient dockerClient, String containerId, String local, String remote) {
        try {
            // String path = "F:\\tmp\\wealth.rar"
            // remote="/tmp/wealth.rar"
            InputStream input = dockerClient
                    .copyArchiveFromContainerCmd(containerId, remote)
                    .exec();
            int index;
            byte[] bytes = new byte[1024];
            FileOutputStream downloadFile = new FileOutputStream(local);
            while ((index = input.read(bytes)) != -1) {
                downloadFile.write(bytes, 0, index);
                downloadFile.flush();
            }
            input.close();
            downloadFile.close();
            return true;
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }
    }

    /**
     * 根据容器名获取容器ID
     *
     * @param dockerClient
     * @param containerName
     * @return
     */
    public static String getContainerIdByName(DockerClient dockerClient, String containerName) {
        String containerId = "";
        List<Container> containers = listContainersCmd(dockerClient);
        for (Container container : containers) {
            List<String> names = Arrays.asList(container.getNames());
            if (!CollectionUtils.isEmpty(names) && names.contains(containerName)) {
                containerId = container.getId();
            }
        }
        return containerId;
    }

}
